package email;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;


public class ThreadManager {
	/**
	 * Single instance of ThreadManager that is instantiated.
	 */
	private static ThreadManager threadManager;
	
	private HashMap<Long, Thread> threads;
	
	private SqlDBController dBController;
	
	
	/**
	 * Private Constructor to allow only this class to create
	 * an instance of ThreadManager
	 */
	private ThreadManager(){
		threads = new HashMap<Long, Thread>();
		dBController = new SqlDBController();
		threads = dBController.loadThreads();
	}
	
	/**
	 * Retrieves the single instance of ThreadManager
	 * for use by other classes.
	 * @return ThreadManager object
	 */
	public synchronized static ThreadManager getInstance(){
		// if we have not initialized the instance
		if(threadManager == null){
			// initialize it
			threadManager = new ThreadManager();
		}
		// return our instance
		return threadManager;
	}
	
	public void createThread(long id, String name, ArrayList<ReceivedMessage> emails){
		Thread newThread = new Thread(id, name, emails);
		dBController.addThread( newThread );
		threads.put(id, newThread);
	}
	
	public void createReplyThread(long id, String name, ArrayList<ReceivedMessage> emails){
		Thread newThread = new Thread(id, name, emails);
		newThread.setReplyThread(true);
		threads.put(id, newThread);
	}
	
	public Thread getThread(long id){
		if(!threads.containsKey(id)){
			// error here, maybe don't want to return null
			// but for the moment that is what we are doing.
			return null;
		}
		else{
			return threads.get(id);
		}
	}
	
	public void unthread(long id){
		Thread toRemove = getThread(id);
		if(toRemove != null){
			dBController.unthread( toRemove );
			removeThread(id);
		}
	}
	
	public void mergeThreads(long id, ArrayList<ReceivedMessage> messagesToMerge, 
			                 ArrayList<Long> threadsToRemove)
	{
		if(threads.containsKey(id)){
			Thread mergeTo = threads.get(id);
			mergeTo.setEmails(messagesToMerge);
			threads.put(id, mergeTo);
			for(int i = 1; i < threadsToRemove.size(); i++){
				removeThread(threadsToRemove.get(i));
			}
			long[] merged = new long[threadsToRemove.size()];
			for(int i = 0; i < threadsToRemove.size(); i++){
				merged[i] = threadsToRemove.get(i);
			}
			dBController.mergeThread(merged, mergeTo);
		}
	}
	
	public void renameThread(long id, long newid, String name){
		Thread t = getThread(id);
		t.setId(newid);
		t.setName(name);
		threads.put(newid, t);
		threads.remove(id);
		dBController.renameThread(id, t, name);
	}
	
	public Thread[] getThreads(){
		Iterator<Long> iter = threads.keySet().iterator();
		Thread[] toReturn = new Thread[threads.keySet().size()];
		int i = 0;
		while(iter.hasNext()){
			toReturn[i++] = threads.get(iter.next());
		}
		
		return toReturn;
	}
	
	public void removeThread(long id){
		threads.remove(id);
	}
	
	public void updateThread(long id, Thread t){
		threads.put(id, t);
	}
	
}
